package com.superbytecode.cloud.web.swagger;

import com.fasterxml.jackson.databind.introspect.AnnotatedField;
import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition;
import com.superbytecode.cloud.common.model.IDict;
import io.swagger.annotations.ApiModelProperty;
import lombok.extern.slf4j.Slf4j;
import springfox.documentation.builders.RequestParameterBuilder;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.schema.ModelPropertyBuilderPlugin;
import springfox.documentation.spi.schema.contexts.ModelPropertyContext;
import springfox.documentation.spi.service.ExpandedParameterBuilderPlugin;
import springfox.documentation.spi.service.contexts.ParameterExpansionContext;

import java.util.Arrays;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * All rights Reserved, Designed By www.super-master.com
 *
 * @ProjectName: beacon-cloud
 * @Package: com.superbytecode.cloud.web.swagger
 * @ClassName: PropertyBuilderPlugin
 * @Description: [Swagger枚举属性增强插件]
 * <p> </p>
 * @Author: [Lance Ting]
 * @Date: 2024/10/22 11:57
 * @Version: V1.0
 * @Copyright: 2024 www.super-master.com Inc. All rights reserved.
 * TODO: 注意,本文件Lance Ting所作,如果转载或使用请标明具体出处!
 **/
@Slf4j
public class PropertyBuilderPlugin implements ModelPropertyBuilderPlugin, ExpandedParameterBuilderPlugin {

    /**
     * 枚举类型属性自动扩展注释
     * 适用于非get请求接口中DTO的属性（有注解@RequestBody标识）
     *
     * @param context context
     */
    @Override
    public void apply(ModelPropertyContext context) {
        context.getBeanPropertyDefinition().map(BeanPropertyDefinition::getField)//
                .map(AnnotatedField::getAnnotated).ifPresent(field -> {
                    ModelPropertyEnum modelPropertyEnum = field.getAnnotation(ModelPropertyEnum.class);
                    ApiModelProperty modelProperty = field.getAnnotation(ApiModelProperty.class);
                    if (Objects.nonNull(modelPropertyEnum) && Objects.nonNull(modelProperty)) {
                        String description = this.getDescription(modelPropertyEnum);
                        SwaggerUtil.append(context, "（" + description + "）");
                    }
                });
    }

    /**
     * 枚举类型属性自动扩展注释
     * 适用于get请求参数中DTO的属性
     *
     * @param context context
     */
    @Override
    public void apply(ParameterExpansionContext context) {
        RequestParameterBuilder requestParameterBuilder = context.getRequestParameterBuilder();
        Optional<ApiModelProperty> propertyOption = context.findAnnotation(ApiModelProperty.class);
        Optional<ModelPropertyEnum> propertyEnumOption = context.findAnnotation(ModelPropertyEnum.class);
        if (propertyOption.isPresent() && propertyEnumOption.isPresent()) {
            ModelPropertyEnum apiModelProperty = propertyEnumOption.get();
            requestParameterBuilder.description(this.getDescription(apiModelProperty));
        }
    }

    /**
     * @param documentationType 类型
     * @return 标识
     */
    @Override
    public boolean supports(DocumentationType documentationType) {
        return true;
    }

    /**
     * 获取注释信息
     * <p>
     * 将枚举信息添加到原注释之后
     * </p>
     *
     * @param modelPropertyEnum 枚举
     * @return 增强注释
     */
    private String getDescription(ModelPropertyEnum modelPropertyEnum) {
        Class<? extends IDict<?>> dictEnum = modelPropertyEnum.dictEnum();
        return Arrays.stream(dictEnum.getEnumConstants())//
                .map(dict -> dict.obtainCode() + "：" + dict.obtainValue())//
                .collect((Collectors.joining("，")));
    }
}